/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package l1j.server.server;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

//import java.util.logging.Logger;

import l1j.server.server.Account;
import l1j.server.server.ClientThread;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_CommonNews;
import l1j.server.server.serverpackets.S_LoginResult;
import l1j.server.server.serverpackets.S_ServerVersion;
import l1j.server.server.utils.SystemUtil;
import l1j.server.server.utils.collections.Maps;

public class LoginController {
	private static LoginController _instance = new LoginController();

	private Map<Integer, ClientThread> _allClients = Maps.newConcurrentMap();

	private AtomicInteger _currentClientId = new AtomicInteger(0);

	private Map<String, Account> _allAccounts = Maps.newConcurrentMap();

	// private static Logger _log = Logger.getLogger(LoginController.class
	// .getName());

	private LoginController() {
	}

	public static LoginController getInstance() {
		return _instance;
	}

	public synchronized void newClientConnect(ClientThread client) {
		client.sendPacket(new S_ServerVersion());
		int newClientId = _currentClientId.incrementAndGet();
		client.setClientId(newClientId);
		_allClients.put(new Integer(newClientId), client);
		System.out.println("第" + newClientId + "號客戶端開始連線..."
				+ client.getHostname());
		System.out.println("使用了 " + SystemUtil.getUsedMemoryMB() + "MB 的記憶體");
		System.out.println("等待客戶端連接...");
	}

	public synchronized void disconnectClient(int clientId) {
		ClientThread client = _allClients.remove(clientId);
		if (client != null) {
			LogoutChar(client);
			LogoutAccount(client);
			client.closeConnection();
			System.out.println("第" + clientId + "號客戶端結束連線..."
					+ client.getHostname());
			System.out.println("使用了 " + SystemUtil.getUsedMemoryMB()
					+ "MB 的記憶體");
			System.out.println("等待客戶端連接...");
		}

	}

	public synchronized void LoginAccount(String accountName, String password,
			ClientThread client) {
		if (_allAccounts.containsKey(accountName)) {
			client.sendPacket(new S_LoginResult(
					S_LoginResult.REASON_ACCOUNT_IN_USE));
			for (ClientThread clients : _allClients.values()) {
				if (clients.getAccount() != null) {
					if (clients.getAccountName().equalsIgnoreCase(accountName)) {
						disconnectClient(clients.getClientId());
					}
				}
			}
			return;
		}

		Account account = Account.load(accountName);
		String ip = client.getIp();
		if (account == null) {
			account = Account.create(accountName, password, ip,
					client.getHostname());
		}
		if (!account.validatePassword(password) || account.isBanned()) {
			client.sendPacket(new S_LoginResult(S_LoginResult.REASON_PASS_WRONG));
			return;
		}

		account.logAccountLogin();
		client.setAccount(account);
		client.sendPacket(new S_LoginResult(S_LoginResult.REASON_LOGIN_OK));
		client.sendPacket(new S_CommonNews());
		_allAccounts.put(accountName, account);
		System.out.println("登入帳號：" + accountName + "(ClientId = "
				+ client.getClientId() + ")");
	}

	public synchronized void LogoutAccount(ClientThread client) {
		if (client.getAccount() != null) {
			System.out.print("帳號登出：" + client.getAccountName() + "...");
			client.getAccount().logAccountLogout();
			_allAccounts.remove(client.getAccountName());
			client.setAccount(null);
		}
	}

	public synchronized L1PcInstance LoginChar(String charName,
			ClientThread client) {
		Account account = client.getAccount();
		if (client.getActiveChar() != null
				|| account.getCurrentPlayer() != null) {
			disconnectClient(client.getClientId());
			return null;
		}
		L1PcInstance pc = L1PcInstance.load(charName);
		if ((pc == null)
				|| !client.getAccountName().equals(pc.getAccountName())) {
			disconnectClient(client.getClientId());
			return null;
		}
		client.setActiveChar(pc);
		client.startAutoSaver();
		account.setCurrentPlayer(pc);
		pc.setNetConnection(client);
		pc.setPacketOutput(client);
		pc.setOpcodes(client.getOpcode());
		System.out.println("登入角色：" + charName + "(account = "
				+ client.getAccountName() + ")");
		return pc;
	}

	public synchronized void LogoutChar(ClientThread client) {
		L1PcInstance pc = client.getActiveChar();
		if (pc != null) {
			System.out.println("角色登出：" + pc.getName() + "(account = "
					+ client.getAccountName() + ")");
			client.stopAutoSaver();
			client.quitGame();
			client.setActiveChar(null);
			client.getAccount().setCurrentPlayer(null);
			System.gc();
		}
	}

	public void disConnectAllClient() {
		for (ClientThread client : _allClients.values()) {
			this.disconnectClient(client.getClientId());
		}
	}

}
